
#include "member_BListWidget.h"
#include "member_BListItem.h"
#include "member_BObject.h"

using namespace BWE;

#define member					(*(member_BListItem*)_ptr)
#define member_allocate()		_ptr = new member_BListItem(this)
#define member_release()		delete (member_BListItem*)_ptr

BListItem::BListItem()
{
	member_allocate();
}
BListItem::BListItem(const BString& text)
{
	member_allocate();
	member.text = text;
}
BListItem::BListItem(Graph graph, const BString& text)
{
	member_allocate();
	member.graph = graph;
	member.text = text;
}
BListItem::BListItem(BIcon* icon, const BString& text)
{
	member_allocate();
	member.icon = icon;
	member.text = text;
}
BListItem::BListItem(BImage* image, const BString& text)
{
	member_allocate();
	member.image = image;
	member.text = text;
}
BListItem::BListItem(BWidget* widget, const BString& text)
{
	member_allocate();
	member.widget = widget;
	member.text = text;
}
BListItem::~BListItem()
{
	member_release();
}

bool BListItem::setVisible(bool visible)
{
	if (member.visible != visible)
	{
		member.visible = visible;
		if (member.visible)
			this->emit(Signal_Show, true);
		else
			this->emit(Signal_Hide, false);
		member.dirtyList();
		return true;
	}
	return false;
}
bool BListItem::visible() const
{
	return member.visible;
}

bool BListItem::setSelected(bool selected)
{
	if (member.list && member.selected != selected)
	{
		return member.list->setItemSelected(this, selected);
	}
	return false;
}
bool BListItem::selected() const
{
	return member.list && member.selected;
}

void BListItem::setChecked(bool checked)
{
	if (member.checked != checked)
	{
		member.checked = checked;
		emit(Signal_Checked, checked);
		this->fresh();
	}
}
bool BListItem::checked() const
{
	return member.checked;
}

bool BListItem::setForm(Form form)
{
	if (member.form != form)
	{
		member.form = form;
		member.dirty = true;
		member.dirtyList();
		return true;
	}
	return false;
}
Form BListItem::form() const
{
	return member.form;
}

bool BListItem::setAlign(Align align)
{
	if (member.align != align)
	{
		member.align = align;
		member.dirty = true;
		member.dirtyList();
		return true;
	}
	return false;
}
Align BListItem::align() const
{
	return member.align;
}

bool BListItem::setSpacing(int spacing)
{
	if (member.spacing != spacing)
	{
		member.spacing = spacing;
		member.dirty = true;
		member.dirtyList();
		return true;
	}
	return false;
}
int BListItem::spacing() const
{
	return member.spacing;
}

bool BListItem::setGraph(Graph graph)
{
	if (member.graph != graph)
	{
		member.graph = graph;
		member.dirty = true;
		member.dirtyList();
		return true;
	}
	return false;
}
Graph BListItem::graph() const
{
	return member.graph;
}

bool BListItem::setIcon(BIcon* icon)
{
	if (member.icon != icon)
	{
		member.icon = icon;
		member.dirtyList();
		return true;
	}
	return false;
}
BIcon* BListItem::icon() const
{
	return member.icon;
}

bool BListItem::setImage(BImage* image)
{
	if (member.image != image)
	{
		member.image = image;
		member.dirtyList();
		emit(Signal_ImageChanged, member.image);
		return true;
	}
	return false;
}
BImage* BListItem::image()
{
	return member.image;
}
const BImage* BListItem::image() const
{
	return member.image;
}

bool BListItem::setColor(BByte r, BByte g, BByte b, BByte a)
{
	return setColor(BColor(r, g, b, a));
}
bool BListItem::setColor(const BColor& color)
{
	if (member.color != color)
	{
		member.color = color;
		if (member.list)
			member.list->fresh();
		return true;
	}
	return false;
}
const BColor& BListItem::color() const
{
	return member.color;
}

bool BListItem::setIconSize(int iconWidth, int iconHeight)
{
	return setIconSize(BSize(iconWidth, iconHeight));
}
bool BListItem::setIconSize(const BSize& iconSize)
{
	if (member.iconSize != iconSize)
	{
		member.iconSize = iconSize;
		member.dirty = true;
		member.dirtyList();
		return true;
	}
	return false;
}
const BSize& BListItem::iconSize() const
{
	return member.ia_iconSize;
}

bool BListItem::setText(const BString& text)
{
	if (member.text != text)
	{
		member.text = text;
		member.dirtyList();
		emit(Signal_TextChanged, member.text);
		return true;
	}
	return false;
}
const BString& BListItem::text() const
{
	return member.text;
}

void BListItem::setTips(const BString& tips)
{
	if (member.tips != tips)
	{
		member.tips = tips;
		object_member(this)->check_emit(Signal_TipsChanged, tips);
	}
}
const BString& BListItem::tips() const
{
	return member.tips;
}

void BListItem::setTextFormat(BTextFormat* textFormat)
{
	if (member.block.format() != textFormat)
	{
		member.block.setFormat(textFormat);
		if (textFormat)
		{
			if (member.list)
				textFormat->styled(member.list->realStyle());
			textFormat->changed(member.text);
		}
		this->emit(Signal_FormatChanged, textFormat);
		member.dirtyList();
	}
}
const BTextFormat* BListItem::textFormat() const
{
	return member.block.format();
}
BTextFormat* BListItem::textFormat()
{
	return member.block.format();
}

void BListItem::setBackground(BByte r, BByte g, BByte b, BByte a)
{
	setBackground(BColor(r, g, b, a));
}
void BListItem::setBackground(const BColor& background)
{
	if (member.background != background)
	{
		member.background = background;
		if (member.list)
			member.list->fresh();
	}
}
const BColor& BListItem::background() const
{
	return member.background;
}

void BListItem::setForeground(BByte r, BByte g, BByte b, BByte a)
{
	setForeground(BColor(r, g, b, a));
}
void BListItem::setForeground(const BColor& foreground)
{
	if (member.foreground != foreground)
	{
		member.foreground = foreground;
		if (member.list)
			member.list->fresh();
	}
}
const BColor& BListItem::foreground() const
{
	return member.foreground;
}

void BListItem::setBorder(int border)
{
	if (member.border != border)
	{
		member.border = border;
		member.dirtyList();
	}
}
int BListItem::border() const
{
	return member.border;
}

void BListItem::setMargin(const BMargin& margin)
{
	if (member.margin != margin)
	{
		member.margin = margin;
		member.dirtyList();
	}
}
const BMargin& BListItem::margin() const
{
	return member.margin;
}

void BListItem::setRadius(const BSize& radius, PartFlag part)
{
	bool changed = false;
	if (member.round.empty())
	{
		member.round = new IRound();
		changed = true;
	}
	if (part & Part_Left && part & Part_Top)
	{
		if (member.round->radiusLeftTop != radius)
		{
			member.round->radiusLeftTop = radius;
			changed = true;
		}
	}
	if (part & Part_Left && part & Part_Bottom)
	{
		if (member.round->radiusLeftBottom != radius)
		{
			member.round->radiusLeftBottom = radius;
			changed = true;
		}
	}
	if (part & Part_Right && part & Part_Top)
	{
		if (member.round->radiusRightTop != radius)
		{
			member.round->radiusRightTop = radius;
			changed = true;
		}
	}
	if (part & Part_Right && part & Part_Bottom)
	{
		if (member.round->radiusRightBottom != radius)
		{
			member.round->radiusRightBottom = radius;
			changed = true;
		}
	}
	if (changed)
	{
		this->fresh();
	}
}
void BListItem::setRadius(const BSize& leftTop, const BSize& rightTop, const BSize& rightBottom, const BSize& leftBottom)
{
	if (member.round.empty() && leftTop.empty() && rightTop.empty() && rightBottom.empty() && leftBottom.empty())
		return;
	bool changed = false;
	if (member.round.empty())
	{
		member.round = new IRound();
		changed = true;
	}
	if (member.round->radiusLeftTop != leftTop)
	{
		member.round->radiusLeftTop = leftTop;
		changed = true;
	}
	if (member.round->radiusRightTop != rightTop)
	{
		member.round->radiusRightTop = rightTop;
		changed = true;
	}
	if (member.round->radiusRightBottom != rightBottom)
	{
		member.round->radiusRightBottom = rightBottom;
		changed = true;
	}
	if (member.round->radiusLeftBottom != leftBottom)
	{
		member.round->radiusLeftBottom = leftBottom;
		changed = true;
	}
	if (changed)
	{
		this->fresh();
	}
}
BSize BListItem::radius(PartFlag part)
{
	if (member.round)
	{
		if (part == Part_LeftTop)
			return member.round->radiusLeftTop;
		if (part == Part_RightTop)
			return member.round->radiusRightTop;
		if (part == Part_RightBottom)
			return member.round->radiusRightBottom;
		if (part == Part_LeftBottom)
			return member.round->radiusLeftBottom;
		return member.round->radiusLeftTop;
	}
	return BSize();
}

bool BListItem::setWidget(BWidget* widget)
{
	if (member.widget != widget)
	{
		if (member.list && member.widget)
		{
			member.list->removeChild(member.widget);
		}
		member.widget = widget;
		if (member.list && member.widget)
		{
			member.list->addChild(member.widget);
			member.widget->setFloating(false);
			member.dirtyList();
		}
		return true;
	}
	return false;
}
BWidget* BListItem::widget() const
{
	return member.widget;
}

bool BListItem::setIndex(int index)
{
	if (BListWidget* list = member.list)
	{
		BList<BListItemHolder>& items = list_member(list)->items;
		int pos = items.index(this);
		if (items.move(pos, index))
		{
			auto end = items.seek(bMax(pos, index));
			for (auto it = items.seek(bMin(pos, index)); it <= end; ++it)
			{
				BListItem* item = *it;
				item->emit(Signal_OrderChanged, it.index());
			}
			this->fresh();
		}
	}
	return false;
}
int BListItem::index() const
{
	if (member.list)
		return member.index;
	return -1;
}

bool BListItem::raise()
{
	if (member.list)
	{
		BList<BListItemHolder>& items = list_member(member.list)->items;
		auto it = items.find(this);
		if (items.move(it, items.begin()))
		{
			for (it = items.begin(); it.valid(); ++it)
			{
				BListItem* item = *it;
				item->emit(Signal_OrderChanged, it.index());
			}
			this->fresh();
			return true;
		}
	}
	return false;
}
bool BListItem::lower()
{
	if (member.list)
	{
		BList<BListItemHolder>& items = list_member(member.list)->items;
		auto it = items.find(this);
		int index = it.index();
		if (items.move(it, items.end()))
		{
			for (it = items.seek(index); it.valid(); ++it)
			{
				BListItem* item = *it;
				item->emit(Signal_OrderChanged, it.index());
			}
			this->fresh();
			return true;
		}
	}
	return false;
}

BListItem* BListItem::prev()
{
	if (BListWidget* list = member.list)
	{
		return list_member(list)->items(member.index - 1);
	}
	return 0;
}
const BListItem* BListItem::prev() const
{
	if (BListWidget* list = member.list)
	{
		return list_member(list)->items(member.index - 1);
	}
	return 0;
}
BListItem* BListItem::next()
{
	if (BListWidget* list = member.list)
	{
		return list_member(list)->items(member.index + 1);
	}
	return 0;
}
const BListItem* BListItem::next() const
{
	if (BListWidget* list = member.list)
	{
		return list_member(list)->items(member.index + 1);
	}
	return 0;
}

bool BListItem::hovered() const
{
	if (BListWidget* list = member.list)
	{
		return list_member(list)->hoveredItem == this;
	}
	return false;
}
bool BListItem::fresh() const
{
	if (BListWidget* list = member.list)
	{
		list->fresh();
		return true;
	}
	return false;
}

BRect BListItem::rect() const
{
	BRect rect = member.rect();
	if (member.list)
		rect += member.list->offset();
	return rect;
}
BRect BListItem::iconRect() const
{
	BRect rect = member.ia_iconRect + member.pos;
	if (member.list)
		rect += member.list->offset();
	return rect;
}
BRect BListItem::textRect() const
{
	BRect rect = member.ia_textRect + member.pos;
	if (member.list)
		rect += member.list->offset();
	return rect;
}
BRect BListItem::textArea() const
{
	BRect rect = member.ia_textArea + member.pos;
	if (member.list)
		rect += member.list->offset();
	return rect;
}

BListWidget* BListItem::listWidget()
{
	return member.list;
}
const BListWidget* BListItem::listWidget() const
{
	return member.list;
}
